
/// MLSDEFORMER source code
/// by Alvaro Cuno, LCG-COPPE-UFRJ 
/// bugs? email-me: alvaroecp@gmail.com
/// January, 2007

#ifndef __SKELETON_H__
#define __SKELETON_H__

#include <vector>
#include <map>
#include <queue>
#include <fstream>
#include <cassert>
#include <cmath>
#include <iostream>

#include "../typedefs.h"

//~ namespace MLS {

using namespace std;

class Skeleton {
   
public:
   
   Skeleton();
   Skeleton(const Skeleton& s);
   Skeleton(const char* filename);
   ~Skeleton();
   
   unsigned int nJoints() const { return joints.size(); } 
   unsigned int nBones()  const { return bones.size(); } 
   
   Point3 getJointPosition(unsigned int i) const { return joints[i]; }
   Bone getBone(unsigned int i) const { return bones[i]; }
   
   void saveAs(const char *filename);
   static Skeleton* load(const char *filename);
   
   /// Transformations
   void rotate(const Point3 &o, const Vector3 &u, Number angle);
   void translate(const Vector3 &t);
   void translateJoint(unsigned int i, const Vector3 &t);
   
   /// Editing operations
   void flipBone(unsigned int idbone);
   void newBone(unsigned int jointID, unsigned int jointIDprev);
   void splitBone(unsigned int idbone);
   void deleteBone(unsigned int idbone);
   
   /// Inserts a new joint
   /// @return the id of the joint
   int newJoint(const Point3 &o);
   void deleteJoint(unsigned int idvertex);
   
   /// Computes distances to all joints on the skeleton
   /// @param id identifier of joint source
   void floodfill_Dijkstra(int id);
   
   /// Build the skeleton graph using the bones array
   void buildGraph();
   
   /// retorna la distancia de v al segmento definido por el bone i
   /// t es un parametro que define el punto mas proximo en el segmento
   /// t es 1 cuando el punto mas cercano esta sobre bone.first
   /// t es 0 cuando el punto mas cercano esta sobre bone.second
   float getDistance(const float *v, unsigned int i, float &t);
   
   /// retorna la eliptica distancia de v al segmento definido por el bone i
   /// t es un parametro que define el punto mas proximo en el segmento
   /// t es 1 cuando el punto mas cercano esta sobre bone.first
   /// t es 0 cuando el punto mas cercano esta sobre bone.second
   float getEllipDistance(const float *v, unsigned int ib, float &t);
   
   /// retorna o ponto elliptico no bone i definido por el parametro t
   Point3 getEllipPointOnBone(unsigned int i, float t);
   
   Vector3 getBoneProjector(const float *v, unsigned int i);
   
   /// Returns the point over bone i defined by parameter t
   Point3 getPointOnBone(unsigned i, float t);
   
   float getDistanceBetweenBone(unsigned int i, unsigned int j);
   
   void computeBonesDistanceTable();
   
   void getBonesOrderList();
   
private:
public:
   
   vector<Point3>             joints;       //< the joints
   vector<Bone>               bones;        //< the bones: it is a pair composed by the id's joint and the id's previous joint
   vector<vector<int> >       graph;        //< the undirected graph is used for performing the Dijkstra path algorithm
   
   vector<Vector3>            atbones;       //< artificial bones used to get the rotation of a bone around itself
   vector<int>                orderList;
   
   vector<int>                bodypart;
   vector<vector<int> >       controller;   //< 
   
   vector<bool>               onlyvisible; // o closetvisible bone predomina sobre o 
                                           //  bone mais proximo na metrica que inclui um caminho ao longo da superficie
   
   /// Skinning variables
   vector<Number>             d;            //< distances vector: it is used to perform the dijkstra algorithm
   vector<bool>               k;            //< flag to specify material properties. TRUE(nothing is done), FALSE(the joint is conisedered as infinity)
   vector<int>                closest_vertex; //< the closest vertex id
   vector<Number>             min_distance_vertex; //< the distance to the closest vertex
   vector<vector<Number> >    dbones;       //< table of distances among bones 
};

//~ }

#endif 
